package com.cancer.common.web;

import java.util.Map;

import javax.servlet.ServletContext;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.web.context.support.WebApplicationContextUtils;

/**
 * 描述：应用程序上下文工具类,通过此类可以获取当前环境下的spring容器； 容器的加载只在程序启动时初始化一次
 * 
 * 2016年4月16日 @author 刘俊
 * 增加了泛型支持
 * 
 * @Company GeekPlus
 * @Project beetle
 * @since 1.0.0
 * @Author ck
 * @Date 2015年12月18日 上午11:59:00
 * @Description
 */
public class ApplicationContextUtils implements ApplicationContextAware {
	private static ApplicationContext context = null;
	
	/**
	 * 描述：初始化方法，只在初始化上下文容器是调用
	 * 
	 * @param sc servlet上下文
	 */
	public static void initialize(ServletContext sc) {
		if (context == null) context = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
	}
	public static void initialize(ApplicationContext sc) {
		if (context == null) context = sc;
	}

//	/**
//	 * 描述：获取spring容器
//	 * 
//	 * @return 返回spring容器applicationcontext
//	 */
//	public static ApplicationContext getWebApplicationContext() {
//		return context;
//	}

	/**
	 * 描述：获取spring容器
	 * 
	 * @return 返回spring容器applicationcontext
	 */
	public static ApplicationContext getApplicationContext() {
		return context;
	}

	/**
	 * 描述：根据实例类型获取spring容器的配置的实例对象
	 * 
	 * @param clazz 实例的类型
	 * @return 返回具体的实例对象
	 * @throws BeansException - 如果bean不存在
	 */
	public static <T> T loadBean(Class<T> clazz) throws BeansException {

		return context.getBean(clazz);
	}
	
	/**
	 * 描述：根据实例类型获取spring容器的配置的实例对象
	 * 
	 * @param clazz 实例的类型
	 * @return 返回具体的实例对象
	 * @throws BeansException - 如果bean不存在
	 */
	public static <T> Map<String, T> loadBeans(Class<T> clazz) throws BeansException {
		
		return context.getBeansOfType(clazz);
	}

	/**
	 * 描述:根据类名称获取spring容器中的实例对象
	 * 
	 * @param beanName 实例名称
	 * @return 返回实例对象
	 * @throws BeansException - 如果bean不存在
	 */
	@SuppressWarnings("unchecked")
	public static <T> T loadBean(String beanName) throws BeansException {
		
		return (T) context.getBean(beanName);
	}
	
	/**
	 * 描述：根据实例类型获取spring容器的配置的实例对象
	 * 
	 * @param clazz 实例的类型
	 * @return 返回具体的实例对象，如果发生异常返回null
	 */
	public static <T> T getBean(Class<T> clazz) {
		try {
			return context.getBean(clazz);
		} catch (Exception e) {
			return null;
		}
	}
	
	
	/**
	 * 描述：根据实例类型获取spring容器的配置的实例对象
	 * 
	 * @param clazz 实例的类型
	 * @return 返回具体的实例对象，如果不存在指定类型bean，返回null
	 */
	public static <T> Map<String, T> getBeans(Class<T> clazz) throws BeansException {
		try {
			return context.getBeansOfType(clazz);
		} catch (Exception e) {
			return null;
		}
	}
	
	/**
	 * 描述:根据类名称获取spring容器中的实例对象
	 * 
	 * @param beanName 实例名称
	 * @return 返回实例对象，如果发生异常返回null
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getBean(String beanName) {
		try {
			return (T) context.getBean(beanName);
		} catch (Exception e) {
			return null;
		}
	}
	
	/**
	 * 描述:根据类名称获取spring容器中的实例对象
	 * 
	 * @param beanName 实例名称
	 * @return 返回实例对象，如果发生异常返回null
	 */
	public static <T> T getBean(String beanName, Class<T> clz) {
		try {
			return (T) context.getBean(beanName, clz);
		} catch (Exception e) {
			return null;
		}
	}
	
	/**
	 * 如果BeanFactory包含一个与所给名称匹配的对象定义，则返回true，否则返回false
	 * 
	 * @param name对象注册名
	 * @return boolean 包含则返回true，否则返回false
	 */
	public static boolean containsBean(String name) {
		
		return context.containsBean(name);
	}

	/**
	 * 判断以给定名字注册的对象定义是一个singleton还是一个prototype。 如果与给定名字相应的对象定义没有被找到，返回false
	 * 
	 * @param name
	 *        对象注册名
	 * @return boolean 单例返回true，否则返回false
	 */
	public static boolean isSingleton(String name) {
		try {
			return context.isSingleton(name);
		} catch (NoSuchBeanDefinitionException e) {
			return false;
		}
	}

	/**
	 * 获得给定名字注册的对象 class类型
	 * 
	 * @param name
	 *        对象注册名
	 * @return Class 注册对象的类型
	 * @throws NoSuchBeanDefinitionException - 如果bean不存在
	 */
	public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {

		return context.getType(name);
	}

	/**
	 * 如果给定的对象名字在对象定义中有别名，则返回这些别名
	 * 
	 * @param name
	 *        对象注册名
	 * @return 对象别名
	 * @throws NoSuchBeanDefinitionException - 如果bean不存在
	 */
	public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
		
		return context.getAliases(name);
	}

	@Override
	public void setApplicationContext(ApplicationContext context) throws BeansException {
		ApplicationContextUtils.context = context;
	}
	
}
